﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Thanhlichtek.BOS.Sync;
using Thanhlichtek.BOS.Bullhorn.BullhornApi;
using System.Threading;
using BrightIdeasSoftware;
using System.IO;
using System.Xml;
using System.Collections;
using System.Configuration;

namespace Thanhlichtek.BOS.Win
{

    public partial class MainForm : Form
    {
        private String _ongageUserName = "erik@talentavenue.com";
        private String _bullhornUserName = "dev1";
        private List<SyncInfoObject> _syncInfoObjects = new List<SyncInfoObject>();
        private String _profileFolder = "Profile";
        private String _bullhornAccountsFile = "Profile\\BullhornAccounts.xml";
        private String _ongageAccountFile = "Profile\\OngageAccount.xml";
        private IList _bullhornAccounts;
        private Ongage.Account _ongageAccount;
        SyncManager syncManager;

        Thread syncThread;

        public MainForm()
        {
            InitializeComponent();
        }

        private void tsbStartSync_Click(object sender, EventArgs e)
        {
            try
            {
                if (tsbStartSync.Text == "Stop synchronizing")
                {
                    try
                    {
                        syncManager.StopSyncList();
                        syncThread.Abort();
                    }
                    catch (Exception)
                    {
                        
                        //throw;
                    }
                    tsbStartSync.Text = "Start synchronizing";
                    tsbStartSync.Image = Properties.Resources.start;
                    return;
                }
                _syncInfoObjects.Clear();
                objectListView1.SetObjects(_syncInfoObjects);
                objectListView1.BuildList();

                syncManager = new SyncManager();

                syncManager.SyncStart += new EventHandler(syncManager_SyncStart);
                syncManager.SyncStop += new EventHandler(syncManager_SyncStop);
                syncManager.ConnectingStart += new EventHandler(syncManager_ConnectingStart);
                syncManager.GettingBullhornListsStart += new EventHandler(syncManager_GettingBullhornListsStart);
                syncManager.GettingBullhornListsStop += new EventHandler(syncManager_GettingBullhornListsStop);
                syncManager.SyncListStart += new EventHandler(syncManager_SyncListStart);
                syncManager.SyncListStop += new EventHandler(syncManager_SyncListStop);
                syncManager.GetClientContactIdsStart += new EventHandler(syncManager_GetClientContactIdsStart);
                syncManager.GetClientContactIdsStop += new EventHandler(syncManager_GetClientContacsOfListStop);

                syncManager.CreateContactSuccess += new EventHandler(syncManager_UpdateListInfo);
                syncManager.UpdateContactSuccess += new EventHandler(syncManager_UpdateListInfo);
                syncManager.SyncContactFail += new EventHandler(syncManager_UpdateListInfo);
                syncManager.SyncContactIgnore += new EventHandler(syncManager_UpdateListInfo);
                syncManager.SyncContactDeletedState += new EventHandler(syncManager_UpdateListInfo);

                syncManager.SyncContactsStart += new EventHandler(syncManager_SyncContactsStart);
                syncManager.SyncError += new EventHandler(syncManager_SyncError);
                syncManager.GettingBullhornListInfoStart += new EventHandler(syncManager_GettingBullhornListInfoStart);

                syncThread = new Thread(new ThreadStart(syncManager.StartSync));
                syncThread.IsBackground = true;
                syncThread.Start();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace);
            }

            
        }

        void syncManager_GettingBullhornListInfoStart(object sender, EventArgs e)
        {
            SetLabelStatus(((SyncEventArgs)e).Message);
        }

        void syncManager_SyncError(object sender, EventArgs e)
        {
            this.Invoke(() => {
                MessageBox.Show(((SyncEventArgs)e).Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                var foundItem = _syncInfoObjects.Find(x => x.Status == "Processing");
                if (foundItem != null)
                {
                    foundItem.Status = "Failed";
                    objectListView1.RefreshObject(foundItem);
                }
                
            });
        }

        void syncManager_UpdateListInfo(object sender, EventArgs e)
        {
            this.Invoke(() =>
            {
                var e2 = (SyncEventArgs)e;
                SyncManager syncManager = (SyncManager)sender;
                var distributionList = e2.BullhornListInfoObj.DistributionList;
                var bullhornAccount = e2.BullhornListInfoObj.BullhornAccountSyncInfoObj.BullhornAccount;
                var foundItem = _syncInfoObjects.Find(x => x.BullhornListId == distributionList.distributionListID && x.BullhornAccount.Id == bullhornAccount.Id);
                foundItem.OngageNotInBullhornAccounts = e2.BullhornListInfoObj.NotExistInBullhorn;

                //counting
                var queryDeleted = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                   where x.State == SyncState.DeletedState
                                  select x;
                foundItem.NoOfDeleted = queryDeleted.ToList().Count;

                var queryFailed = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                  where x.State == SyncState.Failed
                                  select x;
                foundItem.NoOfFailed = queryFailed.ToList().Count;

                var queryCreated = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                  where x.State == SyncState.Created
                                  select x;
                foundItem.NoOfCreatedClientContacts = queryCreated.ToList().Count;

                var queryUpdated = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                   where x.State == SyncState.Updated
                                   select x;
                foundItem.NoOfUpdatedClientContacts = queryUpdated.ToList().Count;

                var queryIgnored = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                   where x.State == SyncState.Ignored
                                   select x;
                foundItem.NoOfIgnored = queryIgnored.ToList().Count;
                //end counting

                foundItem.Progress = String.Format("{0}/{1}",
                    foundItem.NoOfDeleted + foundItem.NoOfFailed + foundItem.NoOfCreatedClientContacts + foundItem.NoOfUpdatedClientContacts + foundItem.NoOfIgnored, 
                    e2.BullhornListInfoObj.ClientContactInfoDict.Count);
                
                objectListView1.RefreshObject(foundItem);

                foundItem.SyncInfoDetailObjects.Clear();
                foreach (var keyValuePair in e2.BullhornListInfoObj.ClientContactInfoDict)
                {
                    var item = keyValuePair.Value;
                    var itemId = keyValuePair.Key;
                    if (item.State == SyncState.NotSynced || item.State == SyncState.Syncing)
                    {
                        continue;
                    }
                    var syncInfoDetailObject = new SyncInfoDetailObject();
                    syncInfoDetailObject.SyncInfoObject = foundItem;
                    syncInfoDetailObject.BullhornId = itemId.ToString();
                    syncInfoDetailObject.ClientContact = item.ClientContact;
                    syncInfoDetailObject.ClientCorporation = item.ClientCorporation;
                    syncInfoDetailObject.Status = item.Message;
                    syncInfoDetailObject.EmailState = item.EmailState;
                    foundItem.SyncInfoDetailObjects.Add(syncInfoDetailObject);
                    syncInfoDetailObject.Owner = item.Owner;
                    
                }


            });
        }


        void syncManager_SyncContactsStart(object sender, EventArgs e)
        {
            SetLabelStatus(((SyncEventArgs)e).Message);
        }

        void syncManager_GetClientContacsOfListStop(object sender, EventArgs e)
        {
            this.Invoke(() => {
                var e2 = (SyncEventArgs)e;
                var contactInfos = e2.BullhornListInfoObj.ClientContactInfoDict.Values;
                var bullhornAccount = e2.BullhornListInfoObj.BullhornAccountSyncInfoObj.BullhornAccount;
                var distributionList = e2.BullhornListInfoObj.DistributionList;
                var foundItem = _syncInfoObjects.Find(x => x.BullhornListId == distributionList.distributionListID && x.BullhornAccount.Id == bullhornAccount.Id);
                if (contactInfos == null)
                {
                    foundItem.NoOfClientContacts = 0;
                }
                else
                {
                    foundItem.NoOfClientContacts = contactInfos.Count();
                }
                objectListView1.RefreshObject(foundItem);
                
            });
        }

        void syncManager_GetClientContactIdsStart(object sender, EventArgs e)
        {
            this.Invoke(() =>
            {
                var e2 = (SyncEventArgs)e;
                SetLabelStatus(((SyncEventArgs)e).Message);
            });
            
        }

       

        void syncManager_SyncStop(object sender, EventArgs e)
        {
            this.Invoke(() =>
            {
                tsbStartSync.Text = "Start synchronizing";
                tsbStartSync.Image = Properties.Resources.start;
                lblStatus.Text = ((SyncEventArgs)e).Message;

                //Generate reports
                List<DistributionListStatisticsItem> statsItems = new List<DistributionListStatisticsItem>();
                List<ContactListItem> contactItems = new List<ContactListItem>();
                //Distribution List Statistics
                foreach (var syncInfoObject in _syncInfoObjects)
                {
                    bool existing = false;
                    var salesPerson = syncInfoObject.SalesPerson;
                    //DistributionListStatisticsItem statsItem;
                    var statsItem = statsItems.Find(x => x.SalesPerson.Equals(salesPerson, StringComparison.OrdinalIgnoreCase));
                    if (statsItem == null)
                    {
                        existing = false;
                        statsItem = new DistributionListStatisticsItem();
                        statsItem.SalesPerson = salesPerson;
                    }
                    else
                    {
                        existing = true;
                    }
                    var details = syncInfoObject.SyncInfoDetailObjects;
                    var notNullDetails = details.FindAll(x => x.ClientContact != null && !x.ClientContact.isDeleted);
                    var nullDetails = details.FindAll(x => x.ClientContact == null);

                    //opt out
                    var queryOptOut = from d in notNullDetails
                                      where (d.ClientContact.massMailOptOut == true) && (!String.IsNullOrEmpty(d.ClientContact.email)) && (d.EmailState != EmailFixedState.NotFixed)
                                      select d;
                    var optOutCount = queryOptOut.ToList().Count;
                    statsItem.OptOut += optOutCount;

                    //no email
                    var queryNoEmail = from d in notNullDetails
                                       where String.IsNullOrEmpty(d.ClientContact.email) || (d.EmailState == EmailFixedState.NotFixed)
                                       select d;
                    var noEmailCount = queryNoEmail.ToList().Count;
                    statsItem.NoEmail += noEmailCount;
                    statsItem.NoEmail += nullDetails.Count;

                    //opt in
                    var optInCount = notNullDetails.Count - optOutCount - noEmailCount;
                    statsItem.OptIn += optInCount;

                    if (statsItem.Total > 0 && existing == false)
                    {
                        statsItems.Add(statsItem);
                        
                    }

                    //contact item
                    foreach (var detail in notNullDetails)
	                {
                        var contactItem = new ContactListItem();
                        if (detail.ClientContact == null)
                        {
                            continue;
                        }
                        contactItem.FirstName = detail.FirstName;
                        contactItem.LastName = detail.LastName;
                        contactItem.Title = detail.Title;
                        contactItem.Company = detail.Company;
                        contactItem.Email = detail.Email;
                        contactItem.State = detail.State;
                        contactItem.ZipCode = detail.ZipCode;
                        contactItem.Owner = detail.OwnerName;

                        contactItem.OptedOut = detail.ClientContact.massMailOptOut ? "yes" : "no";
                        contactItem.DistributionListName = syncInfoObject.BullhornListName;
                        switch (detail.EmailState)
                        {
                            case EmailFixedState.Valid:
                                contactItem.EmailFixed = "";
                                break;
                            case EmailFixedState.Fixed:
                                contactItem.EmailFixed = "yes";
                                break;
                            case EmailFixedState.NotFixed:
                                contactItem.EmailFixed = "no";
                                break;
                            default:
                                contactItem.EmailFixed = "";
                                break;
                        }

                        contactItems.Add(contactItem);
	                }
                    foreach (var nullContact in nullDetails)
                    {
                        var contactItem = new ContactListItem();
                        contactItem.FirstName = "null";
                        contactItem.LastName = "null";
                        contactItem.Title = "null";
                        contactItem.Company = "null";
                        contactItem.Email = "null";
                        contactItem.State = "null";
                        contactItem.ZipCode = "null";
                        contactItem.Owner = "null";
                        contactItem.OptedOut = "null";
                        contactItem.DistributionListName = syncInfoObject.BullhornListName;
                        contactItem.EmailFixed = "null";

                        contactItems.Add(contactItem);
                    }
                }

                var excell_app = new ExcelHelper();
                //creates subheaders
                excell_app.createHeaders(1, 1, "Sales Person");
                excell_app.createHeaders(1, 2, "Opt in");
                excell_app.createHeaders(1, 3, "Opt out");
                excell_app.createHeaders(1, 4, "No email");
                excell_app.createHeaders(1, 5, "Total");
                //add data
                int row = 2;

                foreach (var statsItem in statsItems)
                {
                    excell_app.addData(row, 1, statsItem.SalesPerson);
                    excell_app.addData(row, 2, statsItem.OptIn);
                    excell_app.addData(row, 3, statsItem.OptOut);
                    excell_app.addData(row, 4, statsItem.NoEmail);
                    excell_app.addData(row, 5, statsItem.Total);

                    row++;
                }
                excell_app.addChart(row - 1);
                excell_app.save("Distribution List Statistics");

                //ContactListReport
                var excell_app2 = new ExcelHelper();
                //creates subheaders
                excell_app2.createHeaders(1, 1, "Contact First Name");
                excell_app2.createHeaders(1, 2, "Contact Last Name");
                excell_app2.createHeaders(1, 3, "Title");
                excell_app2.createHeaders(1, 4, "Company");
                excell_app2.createHeaders(1, 5, "Contact Email");
                excell_app2.createHeaders(1, 6, "State");
                excell_app2.createHeaders(1, 7, "Zip Code");
                excell_app2.createHeaders(1, 8, "Owner");
                excell_app2.createHeaders(1, 9, "Opted out");
                excell_app2.createHeaders(1, 10, "Distribution List Name");
                excell_app2.createHeaders(1, 11, "Email Fixed");
                //add data
                row = 2;
                foreach (var contactItem in contactItems)
                {
                    excell_app2.addData(row, 1, contactItem.FirstName);
                    excell_app2.addData(row, 2, contactItem.LastName);
                    excell_app2.addData(row, 3, contactItem.Title);
                    excell_app2.addData(row, 4, contactItem.Company);
                    excell_app2.addData(row, 5, contactItem.Email);
                    excell_app2.addData(row, 6, contactItem.State);
                    excell_app2.addData(row, 7, contactItem.ZipCode);
                    excell_app2.addData(row, 8, contactItem.Owner);
                    excell_app2.addData(row, 9, contactItem.OptedOut);
                    excell_app2.addData(row, 10, contactItem.DistributionListName);
                    excell_app2.addData(row, 11, contactItem.EmailFixed);

                    row++;
                }

                excell_app2.save("ContactListReport");

            });
        }

        void syncManager_SyncStart(object sender, EventArgs e)
        {
            this.Invoke(() =>
            {
                //tsbStartSync.Enabled = false;
                tsbStartSync.Text = "Stop synchronizing";
                tsbStartSync.Image = Properties.Resources.stop;
            });
        }

        void syncManager_SyncListStop(object sender, EventArgs e)
        {
            this.Invoke(() =>
            {
                var e2 = (SyncEventArgs)e;
                //var contactInfos = e2.BullhornListInfoObj.ClientContactInfoDict.Values;
                var bullhornAccount = e2.BullhornListInfoObj.BullhornAccountSyncInfoObj.BullhornAccount;
                var distributionList = e2.BullhornListInfoObj.DistributionList;
                var foundItem = _syncInfoObjects.Find(x => x.BullhornListId == distributionList.distributionListID && x.BullhornAccount.Id == bullhornAccount.Id);

                //counting
                var queryFailed = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                  where x.State == SyncState.Failed
                                  select x;
                foundItem.NoOfFailed = queryFailed.ToList().Count;

                var queryCreated = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                   where x.State == SyncState.Created
                                   select x;
                foundItem.NoOfCreatedClientContacts = queryCreated.ToList().Count;

                var queryUpdated = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                   where x.State == SyncState.Updated
                                   select x;
                foundItem.NoOfUpdatedClientContacts = queryUpdated.ToList().Count;

                var queryIgnored = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                                   where x.State == SyncState.Ignored
                                   select x;
                foundItem.NoOfIgnored = queryIgnored.ToList().Count;
                //end counting

                //debug
                //if (foundItem.NoOfFailed + foundItem.NoOfCreatedClientContacts + foundItem.NoOfUpdatedClientContacts + foundItem.NoOfIgnored < e2.BullhornListInfoObj.ClientContactInfoDict.Count)
                //{
                //    var queryNotSyncedSyncing = from x in e2.BullhornListInfoObj.ClientContactInfoDict.Values
                //                                where x.State == SyncState.NotSynced || x.State == SyncState.Syncing
                //                       select x;
                //    var listTemp = queryNotSyncedSyncing.ToList();
                //    foreach (var item in listTemp)
                //    {
                //        MessageBox.Show(item.ClientContact.email + " " + item.ClientContact.firstName + " " + item.ClientContact.lastName + ": " + item.State.ToString());
                //    }
                //}

                foundItem.Status = "Completed";
                if (e2.BullhornListInfoObj.OngageList == null)
                {
                    foundItem.OngageListName = "(Not Found)";
                }
                else
                {
                    foundItem.OngageListName = e2.BullhornListInfoObj.OngageList.name;
                }
                objectListView1.RefreshObject(foundItem);

            });
        }

        void syncManager_SyncListStart(object sender, EventArgs e)
        {
            this.Invoke(() =>
            {
                var e2 = (SyncEventArgs)e;
                var distributionList = e2.BullhornListInfoObj.DistributionList;
                var foundItem = _syncInfoObjects.Find(x => x.BullhornListId == distributionList.distributionListID && x.BullhornAccount.Id == e2.BullhornListInfoObj.BullhornAccountSyncInfoObj.BullhornAccount.Id);
                if (e2.BullhornListInfoObj.OngageList == null)
                {
                    foundItem.OngageListName = "(Not Found)";
                }
                else
                {
                    foundItem.OngageListName = e2.BullhornListInfoObj.OngageList.name;
                }
                foundItem.Status = "Processing";
                objectListView1.RefreshObject(foundItem);
                objectListView1.SelectObject(foundItem, true);
            });
        }

        void syncManager_GettingBullhornListsStop(object sender, EventArgs e)
        {
            this.Invoke(() => {
                var e2 = (SyncEventArgs)e;
                var lists = e2.BullhornAccountSyncInfoObj.BullhornListInfoDict.Values;
                foreach (var bullhornListInfoItem in lists)
                {
                    var syncInfoObject = new SyncInfoObject();
                    syncInfoObject.BullhornAccount = e2.BullhornAccountSyncInfoObj.BullhornAccount;
                    syncInfoObject.BullhornList = bullhornListInfoItem.DistributionList;
                    //Sales person
                    syncInfoObject.CorporateUser = bullhornListInfoItem.CorporateUser;
                    syncInfoObject.OngageListName = "";
                    syncInfoObject.Status = "Pending";
                    
                    _syncInfoObjects.Add(syncInfoObject);
                    objectListView1.BuildList(true);
                }

            });
        }

        void SetLabelStatus(String message)
        {
            this.Invoke(() => {
                lblStatus.Text = message;
            });
        }

        void syncManager_ConnectingStart(object sender, EventArgs e)
        {
            SetLabelStatus(((SyncEventArgs)e).Message);
        }

        void syncManager_GettingBullhornListsStart(object sender, EventArgs e)
        {
            SetLabelStatus("Getting Bullhorn Lists ...");
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            objectListView1.ShowGroups = false;
            objectListView1.MultiSelect = false;
            objectListView1.FullRowSelect = true;
            objectListView1.UseHotItem = false;
            objectListView1.UseExplorerTheme = true;

            if (!Directory.Exists(_profileFolder))
            {
                Directory.CreateDirectory(_profileFolder);
            }

            try
            {
                //Try to use FiddlerCore
                String useFiddlerCore = ConfigurationManager.AppSettings["UseFiddlerCore"];
                String port = ConfigurationManager.AppSettings["Port"];
                if (!String.IsNullOrEmpty(useFiddlerCore) && useFiddlerCore.Trim().ToUpper().Equals("TRUE"))
                {
                    short portNumber = 0;

                    if (!String.IsNullOrEmpty(port) && Int16.TryParse(port, out portNumber))
                    {
                        System.Net.WebRequest.DefaultWebProxy = new System.Net.WebProxy("127.0.0.1", portNumber);
                        Fiddler.FiddlerApplication.Startup(portNumber, false, false);
                    }
                }

            }
            catch (Exception)
            {
                
                //throw;
            }

        }

        private void objectListView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            var listView = (ObjectListView)sender;
            var selectedObject = (SyncInfoObject)listView.SelectedObject;
            var syncInfoDetailObjects = selectedObject.SyncInfoDetailObjects;

            DetailsForm detailsForm = new DetailsForm();
            detailsForm.SetListViewObjects(syncInfoDetailObjects);
            detailsForm.SetListView2Objects(selectedObject.OngageNotInBullhornAccounts);
            detailsForm.ShowDialog();
            
        }

        private void bullhornAccountsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            BullhornAccountsForm bullhornAccountsForm = new BullhornAccountsForm();
            bullhornAccountsForm.ShowDialog();
        }

        private void ongageAccountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OngageAccountForm ongageAccountForm = new OngageAccountForm();
            ongageAccountForm.ShowDialog();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm aboutForm = new AboutForm();
            aboutForm.ShowDialog();
        }
    }
}
